package com.cmwa.scbp.utils;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import lombok.NonNull;

/**
 * HttpClient工具类
 *
 * @author ex-zhangys
 * @version 1.0
 * @date 2018年11月20日
 */
public class HttpClientUtil {

	private static Logger log = LoggerFactory.getLogger(HttpClientUtil.class);

	private static PoolingHttpClientConnectionManager connMgr;
	private static RequestConfig requestConfig;

	private static final String UTF_8 = "UTF-8";
	private static final int MAX_TIMEOUT = 30000;

	static {
		// 设置连接池
		connMgr = new PoolingHttpClientConnectionManager();
		// 设置连接池大小
		connMgr.setMaxTotal(100);
		connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());

		RequestConfig.Builder configBuilder = RequestConfig.custom();
		// 设置连接超时
		configBuilder.setConnectTimeout(MAX_TIMEOUT);
		// 设置读取超时
		configBuilder.setSocketTimeout(MAX_TIMEOUT);
		// 设置从连接池获取连接实例的超时
		configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT);
		// 在提交请求之前 测试连接是否可用
//		configBuilder.setStaleConnectionCheckEnabled(true);

		requestConfig = configBuilder.build();
	}

	/**
	 * 发送post请求
	 *
	 * @param url
	 *            请求地址
	 * @param headers
	 *            请求头
	 * @param httpEntity
	 *            请求报文实体
	 * @param encoding
	 *            字符集
	 */
	private static String sendPost(@NonNull String url, Map<String, String> headers, HttpEntity httpEntity,
			String encoding) {
		log.info("sendPost：Begion > > >");
		log.debug("url：" + url);
		log.debug("headers：" + JSON.toJSONString(headers));
		if (null != httpEntity) {
			try {
				log.debug("params：" + EntityUtils.toString(httpEntity));
			} catch (IOException e) {
				log.error("httpEntity toString失败", e);
			}
		}
		log.debug("encoding：" + encoding);

		// 请求返回结果
		String resultJson = null;
		// 创建Client
		CloseableHttpClient client = HttpClients.createDefault();
		// 创建HttpPost对象
		HttpPost httpPost = new HttpPost();
		try {
			// post请求信息
			httpPost.setURI(new URI(url));
			httpPost.setConfig(HttpClientUtil.requestConfig);
			httpPost.setEntity(httpEntity);
			httpPost.setHeaders(
					HttpClientUtil.getPostHeaders((httpEntity instanceof StringEntity ? true : false), headers));

			// 发送请求,返回响应对象
			CloseableHttpResponse response = client.execute(httpPost);
			log.debug("response status：" + response.getStatusLine().getStatusCode());

			resultJson = EntityUtils.toString(response.getEntity(), encoding);
			log.debug("response result：" + JSON.toJSONString(resultJson));

		} catch (Exception e) {
			log.error("post请求失败", e);

		} finally {
			httpPost.releaseConnection();
		}

		log.info("sendPost：End > > >");
		return resultJson;
	}

	/**
	 * 发送post json格式请求
	 *
	 * @param url
	 *            请求地址
	 * @param headers
	 *            请求头
	 * @param data
	 *            请求参数
	 * @param encoding
	 *            字符集
	 */
	public static String sendJsonPost(@NonNull String url, Map<String, String> headers, JSONObject data,
			String encoding) {
		StringEntity stringEntity = null;
		if (null != data) {
			stringEntity = new StringEntity(JSON.toJSONString(data), UTF_8);
			// 解决中文乱码问题
			stringEntity.setContentEncoding(UTF_8);
			stringEntity.setContentType("application/json");
		}

		return HttpClientUtil.sendPost(url, headers, stringEntity, encoding);
	}

	/**
	 * 发发送post json格式请求
	 *
	 * @param url
	 *            请求地址
	 * @param headers
	 *            请求头
	 * @param data
	 *            请求参数
	 */
	public static String sendJsonPost(@NonNull String url, Map<String, String> headers, JSONObject data) {
		return sendJsonPost(url, headers, data, UTF_8);
	}

	/**
	 * 发送post json格式请求
	 *
	 * @param url
	 *            请求地址
	 * @param headers
	 *            请求头
	 * @param params
	 *            请求参数
	 */
	public static String sendJsonPost(@NonNull String url, Map<String, String> headers, Map<String, Object> params) {
		return sendJsonPost(url, headers, JSONObject.parseObject(JSON.toJSONString(params)));
	}

	/**
	 * 发送post json格式请求
	 *
	 * @param url
	 *            请求地址
	 * @param data
	 *            请求参数
	 */
	public static String sendJsonPost(@NonNull String url, JSONObject data) {
		return sendJsonPost(url, null, data);
	}

	/**
	 * 发送post json格式请求
	 *
	 * @param url
	 *            请求地址
	 * @param params
	 *            请求参数
	 */
	public static String sendJsonPost(@NonNull String url, Map<String, Object> params) {
		return sendJsonPost(url, JSONObject.parseObject(JSON.toJSONString(params)));
	}

	/**
	 * 发送post map格式请求
	 *
	 * @param url
	 *            请求地址
	 * @param headers
	 *            请求头
	 * @param params
	 *            参数
	 * @param encoding
	 *            字符集
	 */
	public static String sendMapPost(@NonNull String url, Map<String, String> headers, Map<String, Object> params,
			String encoding) {
		UrlEncodedFormEntity urlEntity = null;
		if (null != params && !params.isEmpty()) {
			List<NameValuePair> pairList = new ArrayList<NameValuePair>(params.size());
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				pairList.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
			}
			urlEntity = new UrlEncodedFormEntity(pairList, Charset.forName("utf-8"));
		}

		return HttpClientUtil.sendPost(url, headers, urlEntity, encoding);
	}

	/**
	 * 发送post map格式请求
	 *
	 * @param url
	 *            请求地址
	 * @param headers
	 *            请求头
	 * @param params
	 *            参数
	 */
	public static String sendMapPost(@NonNull String url, Map<String, String> headers, Map<String, Object> params) {
		return HttpClientUtil.sendMapPost(url, headers, params, HttpClientUtil.UTF_8);
	}

	/**
	 * 发送post map格式请求
	 *
	 * @param url
	 *            请求地址
	 * @param params
	 *            参数
	 */
	public static String sendMapPost(@NonNull String url, Map<String, Object> params) {
		return HttpClientUtil.sendMapPost(url, null, params);
	}

	/**
	 * 发送get请求
	 *
	 * @param url
	 *            请求地址
	 * @param params
	 *            请求参数
	 * @param encoding
	 *            编码
	 */
	public static String sendGet(@NonNull String url, Map<String, Object> params, String encoding) {
		log.info("进入get请求方法...");
		log.info("请求入参：url= " + url);
		log.info("请求入参：params=" + JSON.toJSONString(params));
		// 请求结果
		String resultJson = null;
		// 创建client
		CloseableHttpClient client = HttpClients.createDefault();
		// 创建HttpGet
		HttpGet httpGet = new HttpGet();
		try {
			// 创建uri
			URIBuilder builder = new URIBuilder(url);

			// 封装参数
			if (params != null) {
				for (String key : params.keySet()) {
					builder.addParameter(key, params.get(key).toString());
				}
			}
			URI uri = builder.build();
			// 设置请求地址
			httpGet.setURI(uri);
			httpGet.setConfig(HttpClientUtil.requestConfig);
			// 发送请求，返回响应对象
			CloseableHttpResponse response = client.execute(httpGet);
			// 获取响应状态
			int status = response.getStatusLine().getStatusCode();
			if (status == HttpStatus.SC_OK) {
				// 获取响应数据
				resultJson = EntityUtils.toString(response.getEntity(), encoding);
			} else {
				log.error("响应失败，状态码：" + status);
			}
		} catch (Exception e) {
			log.error("发送get请求失败", e);
		} finally {
			httpGet.releaseConnection();
		}
		return resultJson;
	}

	/**
	 * 发送get请求
	 *
	 * @param url
	 *            请求地址
	 * @param params
	 *            请求参数
	 */
	public static String sendGet(@NonNull String url, Map<String, Object> params) {
		return sendGet(url, params, UTF_8);
	}

	/**
	 * 发送get请求
	 *
	 * @param url
	 *            请求地址
	 */
	public static String sendGet(@NonNull String url) {
		return sendGet(url, null, UTF_8);
	}

	/**
	 * 请求头，默认设置
	 *
	 * @param isJsonPost
	 *            json请求
	 * @param headers
	 */
	private static Header[] getPostHeaders(boolean isJsonPost, Map<String, String> headers) {
		headers = null == headers || headers.isEmpty() ? new HashMap<String, String>(1) : headers;
		if (isJsonPost && headers.containsKey("content-type")) {
			headers.put("content-type", "application/json");
		}

		List<Header> headerList = new ArrayList<Header>(headers.size());
		for (Map.Entry<String, String> entry : headers.entrySet()) {
			headerList.add(new BasicHeader(entry.getKey(), entry.getValue()));
		}

		return headerList.toArray(new Header[] {});
	}

	public static String postMsg(String url, String msg) throws HttpException, IOException {
		HttpClient client = new HttpClient();
		client.getHttpConnectionManager().getParams().setConnectionTimeout(20 * 1000);
		client.getHttpConnectionManager().getParams().setSoTimeout(2 * 60 * 1000);

		PostMethod post = new PostMethod(url);
		post.setRequestEntity(new StringRequestEntity(msg, "text/xml", "GBK"));

		client.executeMethod(post);

		return post.getResponseBodyAsString();
	}

}
